import ast
import logging
from collections import defaultdict
from typing import Dict, List, Set, Any

from 程序核心代码.ast节点.节点分析.分析器基类 import 分析器基类
from 程序核心代码.ast节点.节点定义.基础定义.ast节点基础定义 import ast节点基础模型

logger = logging.getLogger(__name__)

class 依赖分析器(分析器基类):
    """依赖分析器类，用于分析节点之间的依赖关系"""
    
    def __init__(self):
        super().__init__()
        self.依赖图: Dict[ast节点基础模型, Set[ast节点基础模型]] = defaultdict(set)
        self.被依赖图: Dict[ast节点基础模型, Set[ast节点基础模型]] = defaultdict(set)
        self.循环依赖: List[List[ast节点基础模型]] = []
        
    def 分析节点(self, 节点: ast节点基础模型) -> Dict[str, Any]:
        """分析指定节点的依赖关系"""
        try:
            if not self.验证节点(节点):
                return {}
                
            # 分析直接依赖
            直接依赖 = self._分析直接依赖(节点)
            self.依赖图[节点].update(直接依赖)
            
            # 更新被依赖关系
            for 依赖节点 in 直接依赖:
                self.被依赖图[依赖节点].add(节点)
                
            # 分析间接依赖
            间接依赖 = self._分析间接依赖(节点)
            
            # 检测循环依赖
            self._检测循环依赖(节点)
            
            # 记录分析结果
            self.分析结果[节点._节点ID] = {
                "直接依赖": [依赖._节点ID for 依赖 in 直接依赖],
                "间接依赖": [依赖._节点ID for 依赖 in 间接依赖],
                "循环依赖": self._获取节点循环依赖(节点)
            }
            
            self.标记已分析(节点)
            return self.分析结果[节点._节点ID]
            
        except Exception as e:
            self.记录分析日志(f"依赖分析失败: {str(e)}", "error")
            return {}
            
    def _分析直接依赖(self, 节点: ast节点基础模型) -> Set[ast节点基础模型]:
        """分析节点的直接依赖关系"""
        直接依赖 = set()
        
        # 分析接口连接的依赖
        for 接口 in 节点.节点接口.values():
            for 连接接口 in 接口.连接列表:
                直接依赖.add(连接接口.节点模型)
                
        # 分析AST节点的依赖
        if hasattr(节点, '_ast节点'):
            for 子节点 in ast.walk(节点._ast节点):
                if isinstance(子节点, (ast.Name, ast.Attribute)):
                    # TODO: 根据变量名和属性查找对应的节点
                    pass
                    
        return 直接依赖
        
    def _分析间接依赖(self, 节点: ast节点基础模型) -> Set[ast节点基础模型]:
        """分析节点的间接依赖关系"""
        间接依赖 = set()
        已访问 = {节点}
        待访问 = list(self.依赖图[节点])
        
        while 待访问:
            当前节点 = 待访问.pop(0)
            if 当前节点 not in 已访问:
                已访问.add(当前节点)
                间接依赖.add(当前节点)
                待访问.extend(self.依赖图[当前节点])
                
        return 间接依赖
        
    def _检测循环依赖(self, 节点: ast节点基础模型) -> None:
        """检测节点的循环依赖"""
        def dfs(当前节点: ast节点基础模型, 路径: List[ast节点基础模型]) -> None:
            if 当前节点 in 路径:
                循环路径 = 路径[路径.index(当前节点):]
                if 循环路径 not in self.循环依赖:
                    self.循环依赖.append(循环路径)
                return
                
            for 依赖节点 in self.依赖图[当前节点]:
                dfs(依赖节点, 路径 + [当前节点])
                
        dfs(节点, [])
        
    def _获取节点循环依赖(self, 节点: ast节点基础模型) -> List[List[str]]:
        """获取节点相关的循环依赖"""
        节点循环依赖 = []
        for 循环 in self.循环依赖:
            if 节点 in 循环:
                节点循环依赖.append([节点._节点ID for 节点 in 循环])
        return 节点循环依赖
        
    def 获取依赖树(self, 节点: ast节点基础模型) -> Dict[str, Any]:
        """获取节点的依赖树结构"""
        def 构建树(当前节点: ast节点基础模型, 已访问: Set[ast节点基础模型]) -> Dict[str, Any]:
            if 当前节点 in 已访问:
                return {"id": 当前节点._节点ID, "循环依赖": True}
                
            树 = {
                "id": 当前节点._节点ID,
                "类型": 当前节点.__class__.__name__,
                "子节点": []
            }
            
            已访问.add(当前节点)
            for 依赖节点 in self.依赖图[当前节点]:
                树["子节点"].append(构建树(依赖节点, 已访问))
            已访问.remove(当前节点)
            
            return 树
            
        return 构建树(节点, set())
        
    def 重置(self) -> None:
        """重置分析器状态"""
        super().重置()
        self.依赖图.clear()
        self.被依赖图.clear()
        self.循环依赖.clear()
        
    def __str__(self) -> str:
        """返回依赖分析器的字符串表示"""
        return f"依赖分析器(节点数={len(self.依赖图)}, 循环依赖数={len(self.循环依赖)})" 